/*
 * Copyright (c) 2012, Asiainfo-Linkage. All rights reserved.
 * Asiainfo-Linkage PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package edu.w106.platform.server;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.servlet.FilterHolder;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.thread.QueuedThreadPool;
import org.mortbay.thread.ThreadPool;

import edu.w106.platform.utils.PropertiesUtil;

/**
 * 
 * @author w106
 *
 */
public class JettyApplication {
    private static Log log = LogFactory.getLog(JettyApplication.class);

    /** 配置文件名称.*/
    private static final String CONF_NAME = "jetty.properties";

    /** 配置参数定义：服务器端口.*/
    private static final String PARAM_PORT = "jetty.port";
    /** 配置参数定义：最大线程数.*/
    private static final String PARAM_MAX_THREAD = "jetty.maxThreads";
    /** 配置参数定义：webapps路径.*/
    private static final String WEBAPPS = "webapps";
    /** 配置参数定义：运行访问的IP.*/
    private static final String PARAM_ALLOW_IPS = "jetty.allowIps";
    /** 临时目录.*/
    private static final String JETTY_TEMP = "work";

    private int serverPort;
    private int maxThreads;
    private AccessFilter accfilter;

    private Server server = null;//new Server(); 
    private final JettThread runThread = new JettThread();

    private void init() {
        PropertiesUtil pu = new PropertiesUtil(CONF_NAME);
        try {
            File tempDir = new File(JETTY_TEMP);
            if (!tempDir.exists()) {
                tempDir.mkdirs();
            }
            Map<String, String> confs = pu.read();
            serverPort = Integer.parseInt(confs.get(PARAM_PORT));
            maxThreads = Integer.parseInt(confs.get(PARAM_MAX_THREAD));
            String allowIps = confs.get(PARAM_ALLOW_IPS);
            String[] ips = allowIps.split(",");
            accfilter = new AccessFilter();
            for (String ip : ips) {
                accfilter.addAccessIpList(ip);
            }
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
    }

    public void startApplication() {
        init();
        initServer();
        initWebApp();
        startWebServer();

    }

    private void initServer() {
        server = new Server();
        //          // 设置线程池
        ThreadPool threadPool = new QueuedThreadPool(maxThreads);
        server.setThreadPool(threadPool);
        // 设置连接参数
        Connector connector = new SelectChannelConnector();
        // 设置监听端口
        connector.setPort(serverPort);
        server.setConnectors(new Connector[] { connector });
    }

    private void initWebApp() {
        List<WarObj> wars = getWars(WEBAPPS);

        for (WarObj war : wars) {
            WebAppContext webContext = new WebAppContext();
            // 访问项目地址
            webContext.setContextPath(war.getContext());
            //启动的war包
            webContext.setWar(war.getWarAbsPath());
            //为每个war添加过滤器.
            FilterHolder f = new FilterHolder(accfilter);
            webContext.addFilter(f, "/*", 1);
            server.addHandler(webContext);

            log.info("add War:" + war);

        }
    }

    private void startWebServer() {
        server.setStopAtShutdown(true);
        server.setSendServerVersion(true);

        runThread.start();

    }

    private String serverInfo() {
        return String
                .format("Server Info:[Listen Port(%s);MaxThread(%s);webApps(%s)]", serverPort, maxThreads, WEBAPPS);
    }

    /**
     * 扫描webapps目录，得到所有的war文件
     * @param webAppsPath
     * @return
     */
    private List<WarObj> getWars(String webAppsPath) {
        List<WarObj> wars = new ArrayList<WarObj>();
        File[] fs = new File(webAppsPath).listFiles(new WarFilter());
        if (fs == null) {
            return wars;
        }
        for (File f : fs) {
            WarObj wo = new WarObj(f.getAbsolutePath());
            wars.add(wo);
        }

        return wars;
    }

    public void stopApplication() {
        try {
            server.stop();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }

    private class JettThread extends Thread {

        @Override
        public void run() {
            try {
                server.start();
                log.info("WebServer启动完成:" + serverInfo());
                server.join();
            } catch (Exception e) {
                log.error("WebServer启动错误:" + e.getMessage(), e);
            }
        }

    }

}
